package com.relytosoft.mizar.media.host.emqx;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.relytosoft.dubhe.common.redis.utils.RedisUtil;
import com.relytosoft.mizar.media.analyze.api.entity.face.AyFaceDisposition;
import com.relytosoft.mizar.media.analyze.api.entity.face.AyFaceTask;
import com.relytosoft.mizar.media.analyze.api.entity.face.AyFaceTaskSon;
import com.relytosoft.mizar.media.analyze.services.service.face.AyFaceDispositionService;
import com.relytosoft.mizar.media.analyze.services.service.face.AyFaceTaskService;
import com.relytosoft.mizar.media.analyze.services.service.face.AyFaceTaskSonService;
import com.relytosoft.mizar.media.camera.services.service.CameraBaseService;
import com.relytosoft.mizar.media.common.constant.AlarmTypeConstants;
import com.relytosoft.mizar.media.common.constant.AyCacheConstants;
import com.relytosoft.mizar.media.common.constant.MediaMqConstants;
import com.relytosoft.mizar.media.common.entity.pojo.dto.AyDispositionPlanDto;
import com.relytosoft.mizar.media.common.enums.DeleteStatusEnum;
import com.relytosoft.mizar.media.common.enums.TaskStatusEnum;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

/**
 * FaceDataMqttMessageListener
 *
 * @Author SunLi
 * @Date: 2022/5/31 14:33
 * @Version 1.0
 */
@Component
public class FaceDataMqttMessageListener implements com.relytosoft.mizar.media.common.emqx.listener.FaceDataMqttMessageListener {

    private static final Logger log = LoggerFactory.getLogger(FaceMqttMessageListener.class);

    @Resource
    private AyFaceDispositionService ayFaceDispositionService;
    @Resource
    private AyFaceTaskSonService taskSonService;
    @Resource
    private AyFaceTaskService taskService;
    @Resource
    private CameraBaseService cameraBaseService;

    @Override
    public void messageArrived(String topic, MqttMessage message) throws Exception {
        if (topic.equals(MediaMqConstants.FACE_DATA_TOPIC)) {
            boolean isConsume = false;
            String mqttMsg = new String(message.getPayload(), StandardCharsets.UTF_8);
            try {
                JSONObject jsonObject = JSON.parseObject(mqttMsg);
                String opType = jsonObject.getString("OpType");
                String data = jsonObject.getString("Data");
                switch (opType) {
                    //更新实时分析任务第三方ID
                    case "updateTaskId":
                        isConsume = updateTaskId(data);
                        break;
                    //更新实时分析任务状态
                    case "updateTaskStatus":
                        isConsume = updateTaskStatus(data);
                        break;
                    //更新布控任务第三方ID
                    case "updateDispositionId":
                        isConsume = updateDispositionId(data);
                        break;
                    //任务创建失败时更新状态
                    case "taskUnusual":
                        isConsume = taskUnusual(data);
                        break;
                    default:
                        break;
                }
                log.info("线程名称：【" + Thread.currentThread().getName() + "】" + "接收的主题：" + topic + ",接收的操作类型：" + opType + "，执行结果：" + isConsume);
            } catch (Exception e) {
                log.info("线程名称：【" + Thread.currentThread().getName() + "】" + "接收的主题：" + topic + ",处理发生错误：" + e.getMessage());
            }
        }
    }

    /**
     * 更新子任务的taskId
     *
     * @param data 任务信息
     * @return 消费结果
     */
    private boolean updateTaskId(String data) {
        JSONObject jsonObject = JSON.parseObject(data);
        Integer sonId = jsonObject.getInteger("id");
        String taskId = jsonObject.getString("taskId");

        return taskSonService.getBaseMapper().update(null, new LambdaUpdateWrapper<AyFaceTaskSon>().set(AyFaceTaskSon::getTaskId, taskId).set(AyFaceTaskSon::getUpdatedBy, "SYSTEM")
                .eq(AyFaceTaskSon::getId, sonId)) == 1;
    }

    /**
     * 更新子任务的状态
     *
     * @param data 任务信息
     * @return 消费结果
     */
    private boolean updateTaskStatus(String data) {
        JSONObject jsonObject = JSON.parseObject(data);
        Integer code = jsonObject.getInteger("code");
        String taskId = jsonObject.getString("taskId");
        String msg = jsonObject.getString("msg");
        AyFaceTaskSon taskSon = taskSonService.getByTaskId(taskId);
        if (taskSon != null) {
            if (code != 0) {
                //更新子任务为异常
                LambdaUpdateWrapper<AyFaceTaskSon> wrapper = new LambdaUpdateWrapper<AyFaceTaskSon>().set(AyFaceTaskSon::getStatus, TaskStatusEnum.UNUSUAL.getValue()).set(AyFaceTaskSon::getUpdatedBy, "SYSTEM").set(AyFaceTaskSon::getErrorReason, msg)
                        .eq(AyFaceTaskSon::getId, taskSon.getId()).eq(AyFaceTaskSon::getStatus, TaskStatusEnum.CREATED.getValue()).eq(AyFaceTaskSon::getIsDeleted, DeleteStatusEnum.NOT_DELETED.getValue());

                boolean updateSonRes = taskSonService.update(null, wrapper);
                if (updateSonRes) {
                    //更新主任务为异常
                    LambdaUpdateWrapper<AyFaceTask> wrapper1 = Wrappers.lambdaUpdate();
                    wrapper1.eq(AyFaceTask::getId, taskSon.getFaceTaskId());
                    List<Integer> status = new ArrayList<>(Arrays.asList(TaskStatusEnum.CREATED.getValue(), TaskStatusEnum.RUNING.getValue()));
                    wrapper1.in(AyFaceTask::getStatus, status);
                    wrapper1.eq(AyFaceTask::getIsDeleted, DeleteStatusEnum.NOT_DELETED.getValue());

                    wrapper1.set(AyFaceTask::getStatus, TaskStatusEnum.UNUSUAL.getValue());
                    wrapper1.set(AyFaceTask::getErrorReason, msg);
                    wrapper1.set(AyFaceTask::getUpdatedBy, "SYSTEM");
                    taskService.getBaseMapper().update(null, wrapper1);
                }
                return updateSonRes;
            } else {
                //更新子任务为运行中
                LambdaUpdateWrapper<AyFaceTaskSon> wrapper = Wrappers.lambdaUpdate();
                wrapper.eq(AyFaceTaskSon::getId, taskSon.getId());
                wrapper.eq(AyFaceTaskSon::getStatus, TaskStatusEnum.CREATED.getValue());
                wrapper.eq(AyFaceTaskSon::getIsDeleted, DeleteStatusEnum.NOT_DELETED.getValue());


                wrapper.set(AyFaceTaskSon::getStatus, TaskStatusEnum.RUNING.getValue());
                wrapper.set(AyFaceTaskSon::getUpdatedBy, "SYSTEM");


                boolean updateSonRes = taskSonService.getBaseMapper().update(null, wrapper) == 1;
                if (updateSonRes) {
                    //更新主任务为已成功启动过
                    LambdaUpdateWrapper<AyFaceTask> wrapper1 = Wrappers.lambdaUpdate();
                    wrapper1.eq(AyFaceTask::getId, taskSon.getFaceTaskId());
                    wrapper1.eq(AyFaceTask::getIsDeleted, DeleteStatusEnum.NOT_DELETED.getValue());

                    wrapper1.set(AyFaceTask::getIsStartUp, 1);
                    taskService.getBaseMapper().update(null, wrapper1);
                    //更新主任务为运行中
                    taskService.taskStatusHandle(taskSon.getFaceTaskId(), TaskStatusEnum.RUNING.getValue());
                }
                return updateSonRes;
            }
        } else {
            return false;
        }
    }

    private boolean updateDispositionId(String data) {
        Map<String, Object> map = JSONObject.parseObject(data, new TypeReference<Map<String, Object>>() {
        });
        Integer id = (Integer) map.get("id");
        String dispositionId = (String) map.get("dispositionId");

        //根据任务ID查询
        AyFaceDisposition ayFaceDisposition = ayFaceDispositionService.getById(id);
        ayFaceDisposition.setDispositionId(dispositionId);

        //当获取到返回的布控ID说明任务已经开始
        ayFaceDisposition.setStatus(1);
        ayFaceDisposition.setDefenseStatus(1);
        ayFaceDisposition.setBeginTime(LocalDateTime.now());
        AyDispositionPlanDto ayDispositionPlanDto = getAyDispositionPlanDto(ayFaceDisposition);
        //修改状态并存入缓存和redis
        RedisUtil.set(AyCacheConstants.CONTROL_FACE_CONDITION + dispositionId, JSON.toJSONString(ayDispositionPlanDto));
        return ayFaceDispositionService.updateById(ayFaceDisposition);
    }

    private AyDispositionPlanDto getAyDispositionPlanDto(AyFaceDisposition ayFaceDisposition) {
        AyDispositionPlanDto ayDispositionPlanDto = new AyDispositionPlanDto();
        ayDispositionPlanDto.setDispositionId(ayFaceDisposition.getDispositionId());
        ayDispositionPlanDto.setTaskName(ayFaceDisposition.getName());
        ayDispositionPlanDto.setBeginTime(ayFaceDisposition.getTempBeginTime());
        ayDispositionPlanDto.setEndTime(ayFaceDisposition.getTempEndTime());
        ayDispositionPlanDto.setPlanType(ayFaceDisposition.getPlanType());
        ayDispositionPlanDto.setPlanInfoNum(ayFaceDisposition.getPlanInfoNum());
        ayDispositionPlanDto.setPlanInfoList(ayFaceDisposition.getPlanInfoList());
        ayDispositionPlanDto.setDeviceId(ayFaceDisposition.getDispositionRangeDevice());
        ayDispositionPlanDto.setCameraCode(cameraBaseService.findCameraNameOrCodeById(ayFaceDisposition.getDispositionRangeDevice(), 2));
        ayDispositionPlanDto.setCameraName(cameraBaseService.findCameraNameOrCodeById(ayFaceDisposition.getDispositionRangeDevice(), 1));
        ayDispositionPlanDto.setAlarmTypeId(AlarmTypeConstants.FACE_ALARM_CONTROL);
        return ayDispositionPlanDto;
    }

    /**
     * 任务创建失败时更新状态
     *
     * @param data 任务信息
     * @return 消费结果
     */
    private boolean taskUnusual(String data) {
        JSONObject jsonObject = JSON.parseObject(data);
        Integer id = jsonObject.getInteger("id");
        String msg = jsonObject.getString("msg");
        AyFaceTaskSon taskSon = taskSonService.getById(id);
        if (taskSon != null) {
            //更新子任务为异常
            LambdaUpdateWrapper<AyFaceTaskSon> wrapper = new LambdaUpdateWrapper<AyFaceTaskSon>().set(AyFaceTaskSon::getStatus, TaskStatusEnum.UNUSUAL.getValue()).set(AyFaceTaskSon::getUpdatedBy, "SYSTEM").set(AyFaceTaskSon::getErrorReason, msg)
                    .eq(AyFaceTaskSon::getId, taskSon.getId()).eq(AyFaceTaskSon::getStatus, TaskStatusEnum.CREATED.getValue()).eq(AyFaceTaskSon::getIsDeleted, DeleteStatusEnum.NOT_DELETED.getValue());

            boolean updateSonRes = taskSonService.update(null, wrapper);
            if (updateSonRes) {
                //更新主任务为异常
                LambdaUpdateWrapper<AyFaceTask> wrapper1 = Wrappers.lambdaUpdate();
                wrapper1.eq(AyFaceTask::getId, taskSon.getFaceTaskId());
                wrapper1.eq(AyFaceTask::getStatus, TaskStatusEnum.CREATED.getValue());
                wrapper1.eq(AyFaceTask::getIsDeleted, DeleteStatusEnum.NOT_DELETED.getValue());

                wrapper1.set(AyFaceTask::getStatus, TaskStatusEnum.UNUSUAL.getValue());
                wrapper1.set(AyFaceTask::getErrorReason, msg);
                wrapper1.set(AyFaceTask::getUpdatedBy, "SYSTEM");
                taskService.getBaseMapper().update(null, wrapper1);
            }
            return updateSonRes;

        } else {
            return false;
        }
    }
}
